package com.yunchang.spring.visitor.core.invoker;

import com.yunchang.spring.visitor.core.annotation.*;
import com.yunchang.spring.visitor.core.cache.ICache;
import com.yunchang.spring.visitor.core.constant.ContentType;
import com.yunchang.spring.visitor.core.exception.InvokeException;
import com.yunchang.spring.visitor.core.handler.request.IRequestHandler;
import com.yunchang.spring.visitor.core.paramtype.HeaderParamsMap;
import com.yunchang.spring.visitor.core.paramtype.UrlParamsMap;
import com.yunchang.spring.visitor.core.service.IRestfulService;
import com.yunchang.spring.visitor.core.utils.MapUtil;
import com.yunchang.spring.visitor.core.utils.TypeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.AopProxy;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.*;

/**
 * <pre>
 * 默认的Service反射调用器。
 *
 * Created by jasontujun on 2018/1/10.
 * Modified by zachary on 2018/1/22。
 *      - modify the strategy of request result cache
 *      - The reflection structure is optimized, and it does not have to be reflected every time.
 * Modified by zachary on 2019/9/17。
 *      - support json/xml contentType
 * </pre>
 */
@Component
public class DefaultServiceInvoker implements IRestfulInvoker, IServiceInvoker, ApplicationContextAware {

    /**
     * 将字符串转化为对应T类型的对象。
     * 该接口的实现类，必须包含无参的构造方法
     */
    public interface TypeConverter<T> {
        T convert(String value);
    }


    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final String CONNECTOR = "&";

    // Spring应用上下文环境
    private ApplicationContext applicationContext;

    // 所有Service的信息
    private Map<String, ServiceInfo> serviceMap = new HashMap<>();

    // 针对方法返回结果的缓存
    private ICache cache;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        //加载服务类
        initReflectiveServices();
    }

    @Override
    public void invoke(String namespace, String serviceName, String methodName, HttpServletRequest request,
                       IRequestHandler requestHandler, InvokerCallback callback) {
        Map<String, String> originParams = null;// 原始参数
        String httpContent = null;// InputStream中的内容
        try {
            ServiceInfo serviceInfo = serviceMap.get(namespace + CONNECTOR + serviceName);
            if (serviceInfo == null) {
                // 根据serviceName找不到service
                throw new InvokeException(String.format("Service [%s] not found", serviceName));
            }

            MethodInfo methodInfo = serviceInfo.methods.get(methodName);
            if (methodInfo == null) {
                // 根据methodName找不到method
                throw new InvokeException(String.format("Method [%s] not found", methodName));
            }

            // method没有@ReflectiveMethod注解，不允许调用
            if (methodInfo.reflectiveAnnotation == null) {
                throw new InvokeException(String.format("Method [%s] cannot invoke without @ReflectiveMethod", methodName));
            }

            // 反射Service的方法声明的参数列表
            Parameter[] realParams = methodInfo.method.getParameters();
            // @ReflectiveMethod注解指定的参数列表
            String[] annotationParams = methodInfo.reflectiveAnnotation.params();
            // 原始入参
            originParams = requestHandler.getParams(request);
            // 过滤后的入参
            Map<String, String> params = null;
            // 获取入参
            boolean isForm = (methodInfo.reflectiveAnnotation.contentType() == ContentType.FORM);
            if (isForm) {
                // 对原始入参做参数过滤
                params = doInputParamsFilter(serviceInfo.reflectiveAnnotation.input(), methodName, originParams);
            } else {
                httpContent = requestHandler.getHttpContent(request);
                // 如果Service的方法声明的参数列表不为空，且@ReflectiveMethod注解指定了参数列表，
                // 或Service的方法声明的只有1个Map类型参数，且@ReflectiveMethod注解未指定参数列表
                // 则将httpContent转为Map类型，后续方法调用时，对每个参数进行赋值映射
                if ((realParams.length != 0 && annotationParams.length != 0) ||
                        (realParams.length == 1 && Map.class.isAssignableFrom(realParams[0].getType()))) {
                    params = requestHandler.parseToMap(httpContent, methodInfo.reflectiveAnnotation.contentType());
                    // 对入参做参数过滤
                    params = doInputParamsFilter(serviceInfo.reflectiveAnnotation.input(), methodName, params);
                }
            }

            // 返回结果
            Object result = null;

            // 如果有@VisitorCache注解，优先从缓存里查询
            ReflectiveCache cacheAnnotation = methodInfo.cacheAnnotation == null ?
                    serviceInfo.cacheAnnotation : methodInfo.cacheAnnotation;
            String key = null;
            if (cacheAnnotation != null && cache != null) {
                Map<String, String> copyParams = params == null ? null : new HashMap<>(params);
                if (isForm) {
                    key = cache.generateKey(serviceName, methodName, copyParams, cacheAnnotation.exclude());
                } else {
                    key = cache.generateKey(serviceName, methodName, httpContent);
                }
                if (!StringUtils.isEmpty(key)) {
                    result = cache.get(key);
                }
            }
            // 如果缓存存在，则直接返回
            if (result != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug(String.format("[%s].[%s] has cache, return cache!", serviceName, methodName));
                }
                if (callback != null) {
                    callback.onResponse(request, namespace, serviceName, methodName, result, originParams, httpContent);
                }
            }

            // 方法真实需要的参数值
            Object[] allParamsValue = new Object[realParams.length];
            // 将对应类型放到对应的参数中(类型参数)
            putClassValue(methodInfo, realParams, allParamsValue, request);
            // 将headerparams,urlparams,params 中的参数根据注解放入对应的参数中（位置参数）
            putLocationValue(methodInfo, realParams, allParamsValue, params, httpContent);

            result = methodInfo.method.invoke(serviceInfo.service, allParamsValue);
            //输出字段过滤
            result = doOutParamsFilter(serviceInfo.reflectiveAnnotation.output(), methodName, methodInfo.method, result);

            // 如果有@VisitorCache注解，且方法返回result不为null，则缓存返回结果
            if (cacheAnnotation != null && cache != null && !StringUtils.isEmpty(key) && result != null) {
                cache.set(key, result, cacheAnnotation.expire(), cacheAnnotation.unit());
            }
            if (callback != null) {
                callback.onResponse(request, namespace, serviceName, methodName, result, originParams, httpContent);
            }
        } catch (Exception e) {
            logger.error("", e);
            if (callback != null) {
                callback.onException(request, namespace, serviceName, methodName, e, originParams, httpContent);
            }
        }
    }

    @Override
    public Object invokeRestful(String namespace, String serviceName, String id,
                                HttpServletRequest request, Map<String, String> paramMap)
            throws Exception {
        ServiceInfo serviceInfo = serviceMap.get(namespace + CONNECTOR + serviceName);
        if (serviceInfo == null) {
            // 根据serviceName找不到service
            throw new InvokeException(String.format("Service [%s] not found", serviceName));
        }

        if (serviceInfo.service instanceof IRestfulService) {
            IRestfulService service = (IRestfulService) serviceInfo.service;
            //得到请求方法
            HttpMethod httpMethod = HttpMethod.valueOf(request.getMethod());
            Method method;
            switch (httpMethod) {
                case GET:
                    if (StringUtils.isEmpty(id)) {
                        method = service.getClass().getMethod("list", Map.class);
                    } else {
                        method = service.getClass().getMethod("get", String.class, Map.class);
                    }
                    break;
                case POST:
                    if (StringUtils.isEmpty(id)) {
                        method = service.getClass().getMethod("add", Map.class);
                    } else {
                        method = service.getClass().getMethod("update", String.class, Map.class);
                    }
                    break;
                case DELETE:
                    method = service.getClass().getMethod("remove", String.class, Map.class);
                    break;
                default:
                    throw new InvokeException("RestfulController can't support HttpMethod:" + httpMethod);
            }

            if (method == null) {
                // 根据methodName找不到method
                throw new InvokeException("restful method not found");
            }
            // 访问控制
            if (!checkAllowMethod(serviceInfo.restful, method.getName())) {
                throw new InvokeException(String.format("namespace: [%s] service: [%s] Method: [%s] is deny", namespace, serviceName, method.getName()));
            }

            // 根据filter过滤入参
            paramMap = doInputParamsFilter(serviceInfo.reflectiveAnnotation.input(), method.getName(), paramMap);
            // 执行方法
            Object ret;
            if (StringUtils.isEmpty(id)) {
                ret = method.invoke(service, paramMap);
            } else {
                ret = method.invoke(service, id, paramMap);
            }
            //根据filter过滤出参
            return doOutParamsFilter(serviceInfo.reflectiveAnnotation.output(), method.getName(), method, ret);
        }
        throw new InvokeException("Illegal service : not IRestfulService");
    }

    /**
     * 过滤输入的参数
     *
     * @param params     注解 ReflectiveService.input
     * @param methodName 方法名
     * @param paramMap   请求入参
     * @return 返回按照filter过滤之后的入参
     */
    private Map<String, String> doInputParamsFilter(Params[] params, String methodName, Map<String, String> paramMap) {
        // Params[] params = filterAnnotation.input();
        if (params == null || params.length == 0) {
            return paramMap;
        }
        for (Params param : params) {
            if (methodName.equals(param.methodName())) {
                String[] inputAllowParam = param.params();
                // 过滤入参(第一个Map类型)
                Map realParams = new HashMap<String, String>(paramMap);
                if (inputAllowParam != null && inputAllowParam.length > 0) {
                    // 如果@ServiceParam的input注解不为空，则对第一个类型为Map的参数进行过滤
                    realParams = MapUtil.filterParams(paramMap, inputAllowParam, true);
                }
                return realParams;
            }
        }
        return new HashMap<String, String>(paramMap);
    }

    /**
     * 过滤输出的参数
     *
     * @param params     ReflectiveService.ourput
     * @param methodName 方法名字（有可能为别名）
     * @param method     方法（有可能为代理方法）
     * @param ret        方法返回值
     * @return 按照filter过滤之后的结果
     */
    private Object doOutParamsFilter(Params[] params, String methodName, Method method, Object ret) {
        //Params[] params = filterAnnotation.output();
        if (params == null || params.length == 0) {
            return ret;
        }

        for (Params param : params) {
            if (methodName.equals(param.methodName())) {
                String[] outputAllowParam = param.params();
                // 过滤返回值(Map类型或List<Map>类型)
                if (outputAllowParam != null && outputAllowParam.length > 0) {
                    // 如果@ServiceParam的output注解不为空，则过滤返回值
                    if (Map.class.isAssignableFrom(method.getReturnType())) {
                        // 如果返回值是Map类型，则认为是数据对象的键值对集合，对Map进行过滤
                        return MapUtil.filterParams((Map) ret, outputAllowParam, true);
                    } else if (List.class.isAssignableFrom(method.getReturnType())) {
                        // 如果返回值是List类型，则认为是数据对象列表，再对列表中每个Map类型对象进行过滤
                        List retLis = (List) ret;
                        List newRetList = new ArrayList();
                        for (Object item : retLis) {
                            if (Map.class.isAssignableFrom(item.getClass())) {
                                // 如果List里的对象是Map，则进行过滤
                                newRetList.add(MapUtil.filterParams((Map) item, outputAllowParam, true));
                            } else {
                                // 如果List里的对象不是Map，则不过滤
                                newRetList.add(item);
                            }
                        }
                        return newRetList;
                    }
                    // 如果返回值是非Map或List类型，则不进行返回值过滤
                }
            }
        }

        return ret;
    }

    /**
     * 处理ReflectiveMethod的params指定的参数列表的赋值映射。
     * @param methodInfo 方法info
     * @param realParams 方法声明的参数列表
     * @param allParamsValue 赋值映射后的所有的参数值
     * @param params 请求表单的参数Map
     * @param httpContent 请求表单的参数Map
     */
    private void putLocationValue(MethodInfo methodInfo, Parameter[] realParams, Object[] allParamsValue,
                                  Map<String, String> params, String httpContent) {
        // @ReflectiveMethod注解指定的参数列表
        String[] paramNames = methodInfo.reflectiveAnnotation.params();
        //得到此时数组中 为空的元素下标
        List<Integer> nullIndexes = new ArrayList<>();
        for (int i = 0; i < allParamsValue.length; i++) {
            if (allParamsValue[i] == null) {
                nullIndexes.add(i);
            }
        }

        // 如果@ReflectiveMethod注解的params参数名列表为空，则两种可能：
        // 1.方法声明没有参数 2.方法声明只有一个map类型或String类型的参数
        if (paramNames.length == 0) {
            if (nullIndexes.size() == 0) {
                // 方法声明没有参数【无params参】，什么都不做
            } else if (nullIndexes.size() == 1) {
                // 方法声明的参数只有一个，为map类型，且ContentType是表单
                if (methodInfo.reflectiveAnnotation.contentType() == ContentType.FORM &&
                        Map.class.isAssignableFrom(realParams[nullIndexes.get(0)].getType())) {
                    allParamsValue[nullIndexes.get(0)] = params;
                }
                // 方法声明的参数为只有一个，String类型，且ContentType是JSON或XML
                else if ((methodInfo.reflectiveAnnotation.contentType() == ContentType.JSON
                        || methodInfo.reflectiveAnnotation.contentType() == ContentType.XML)) {
                    if (String.class.isAssignableFrom(realParams[nullIndexes.get(0)].getType())) {
                        allParamsValue[nullIndexes.get(0)] = httpContent;
                    } else if (Map.class.isAssignableFrom(realParams[nullIndexes.get(0)].getType())) {
                        allParamsValue[nullIndexes.get(0)] = params;
                    } else {
                        throw new InvokeException(String.format("Method [%s] defined parameter type must be String or Map!",
                                methodInfo.method.getName()));
                    }
                } else {
                    throw new InvokeException(String.format("Method [%s] defined parameter type error!",
                            methodInfo.method.getName()));
                }
            } else {
                // @ReflectiveMethod注解的params参数列表为空，但方法声明的参数多于1个
                throw new InvokeException(String.format("Method [%s] @ReflectiveMethod parameter length is not the same as method define!",
                        methodInfo.method.getName()));
            }
        } else {
            // 如果@ReflectiveMethod注解的params列表不为空，则必须和方法声明的参数列表一致
            if (nullIndexes.size() != paramNames.length) {
                throw new InvokeException(String.format("Method [%s] @ReflectiveMethod parameter length is not the same as method define!",
                        methodInfo.method.getName()));
            }
            Class<?>[] paramTypes = methodInfo.method.getParameterTypes();
            //逐个赋值
            for (int i = 0; i < paramNames.length; i++) {
                Class paramType = paramTypes[nullIndexes.get(i)];
                allParamsValue[nullIndexes.get(i)] = TypeUtil.parseValue(params.get(paramNames[i]), paramType);
            }
        }
    }

    /**
     * 处理特殊类型的参数的赋值映射。
     * @param methodInfo     方法info
     * @param realParams     方法声明的参数列表
     * @param allParamsValue 赋值映射后的所有的参数值
     * @param request        请求
     * @throws IOException
     */
    private void putClassValue(MethodInfo methodInfo, Parameter[] realParams, Object[] allParamsValue, HttpServletRequest request) throws IOException {
        String methodName = methodInfo.method.getName();
        // 将http的请求流，赋值到对应位置的参数中(只有POST表单的请求，才会赋值InputStream)
        if (methodInfo.reflectiveAnnotation.contentType() == ContentType.FORM) {
            putValue(realParams, InputStream.class, methodName, allParamsValue, request.getInputStream());
        }
        // 将http的请求方式，赋值到对应位置的参数中
        putValue(realParams, HttpMethod.class, methodName, allParamsValue, HttpMethod.valueOf(request.getMethod()));
        // 将http的请求体，赋值到对应位置的参数中
        putValue(realParams, HttpServletRequest.class, methodName, allParamsValue, request);
        // 将请求url中的参数
        putValue(realParams, UrlParamsMap.class, methodName, allParamsValue,
                new UrlParamsMap((Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE)));
        //将请求头部，复制到对应位置的参数中
        putValue(realParams, HeaderParamsMap.class, methodName, allParamsValue, getRequestHeaders(request));
    }

    //判断方法定义的参数中 是否存在clazz类型的参数
    private void putValue(Parameter[] realParams, Class<?> clazz, String methodName, Object[] allParamsValue, Object value) {
        int locate = -1;
        for (int i = 0; i < realParams.length; i++) {
            Parameter realParam = realParams[i];
            //有重复的类型参数
            if (locate != -1 && realParam.getType() == clazz) {
                throw new InvokeException(String.format("Method [%s] has Duplicate " + clazz.getName(),
                        methodName));
            }
            if (realParam.getType() == clazz) {
                locate = i;
            }
        }
        if (locate != -1) {
            allParamsValue[locate] = value;
        }
    }

    /**
     * 获取请求的头信息
     *
     * @param request 请求
     * @return 返回请求头部信息
     */
    private HeaderParamsMap getRequestHeaders(HttpServletRequest request) {
        HeaderParamsMap map = new HeaderParamsMap();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }

    /**
     * 加载所有@ReflectiveService注解的Service以及其@ReflectiveMethod注解的方法
     */
    private void initReflectiveServices() {
        // 遍历所有service
        Map<String, Object> allBeanNames = applicationContext.getBeansWithAnnotation(Service.class);
        allBeanNames.forEach((beanName, bean) -> {
            // 获取真正的service类对象(不是动态代理对象)
            Object realObj = getTargetFromProxy(bean);
            if (realObj == null) {
                realObj = bean;
            }

            //先从类本身查找，如果有@ReflectiveService注解，则添加
            if (realObj.getClass().getAnnotation(ReflectiveService.class) != null) {
                saveServiceInfo(realObj.getClass(), bean);
            }

            // 再从所有接口进行查找，如果有@ReflectiveService注解，则添加
            List<Class<?>> interfaceClazzList = getReflectiveInterfaces(realObj);
            if (interfaceClazzList != null) {
                for (Class<?> interfaceClazz : interfaceClazzList) {
                    saveServiceInfo(interfaceClazz, bean);
                }
            }
        });
        logger.info(String.format("all visitor interface finish init!,size is %s", serviceMap.size()));
    }

    // 保存每个带@ReflectiveService注解的类或接口的方法信息
    private void saveServiceInfo(Class<?> annotationClass, Object proxyBean) {
        ReflectiveService serviceAnnotation = annotationClass.getAnnotation(ReflectiveService.class);
        if (serviceAnnotation == null) {
            return;
        }
        ServiceInfo serviceInfo = new ServiceInfo(proxyBean, serviceAnnotation,
                annotationClass.getAnnotation(ReflectiveCache.class),
                annotationClass.getAnnotation(Restful.class));

        // 当前注解所在类下声明的方法(不含父类继承的方法)，
        Method[] realMethods = annotationClass.getDeclaredMethods();

        //取出代理类中的代理方法
        Method[] proxyMethods;
        if (annotationClass.equals(proxyBean.getClass())) {
            proxyMethods = null;
        } else {
            proxyMethods = proxyBean.getClass().getDeclaredMethods();
        }

        for (Method realMethod : realMethods) {
            // @ReflectiveMethod注解必须是在public方法下
            if (!Modifier.isPublic(realMethod.getModifiers())) {
                continue;
            }
            ReflectiveMethod methodAnnotation = AnnotationUtils.findAnnotation(realMethod, ReflectiveMethod.class);
            if (methodAnnotation != null) {
                //别名不为空则使用别名，否则使用方法名
                String methodName = realMethod.getName();
                if (methodAnnotation.alias().length() != 0) {
                    methodName = methodAnnotation.alias();
                }
                //判断该service中是否已经有同名方法（或别名）存在
                if (serviceInfo.methods.get(methodName) != null) {
                    throw new BeanCreationException("service：" + serviceAnnotation.value() + "中存在同名的method：" + methodName);
                }

                serviceInfo.methods.put(methodName, new MethodInfo(getProxyMethod(proxyMethods, realMethod),
                        methodAnnotation, realMethod.getAnnotation(ReflectiveCache.class)));
            }
        }
        //判断注解ReflectiveService是否存在同名(namespace+service)
        String uniqueName = serviceAnnotation.namespace() + CONNECTOR + serviceAnnotation.value();
        if (serviceMap.get(uniqueName) != null) {
            throw new BeanCreationException("存在同名的 service：" + uniqueName);
        }
        serviceMap.put(uniqueName, serviceInfo);
    }

    /**
     * 判断restful注解中 是否允许methodName
     *
     * @param restful    Restful注解
     * @param methodName 方法名字
     * @return 是否允许该方法访问
     */
    private boolean checkAllowMethod(Restful restful, String methodName) {
        if (restful == null) {
            return true;
        }
        try {
            if ("get".equalsIgnoreCase(methodName)) {
                return restful.get();
            }
            if ("list".equalsIgnoreCase(methodName)) {
                return restful.list();
            }
            if ("add".equalsIgnoreCase(methodName)) {
                return restful.add();
            }
            if ("remove".equalsIgnoreCase(methodName)) {
                return restful.remove();
            }
            if ("update".equalsIgnoreCase(methodName)) {
                return restful.update();
            }
        } catch (IllegalArgumentException e) {
            return true;
        }
        return true;
    }

    /**
     * 根据真实方法,获取代理方法
     *
     * @param proxyMethods 代理方法（有可能为null）
     * @param realMethod   真实的方法
     * @return 动态代理的方法
     */
    private Method getProxyMethod(Method[] proxyMethods, Method realMethod) {
        //proxyMethods 表示没有代理
        if (proxyMethods == null) {
            return realMethod;
        }
        for (Method proxyMethod : proxyMethods) {
            if ((proxyMethod.getName().equals(realMethod.getName()))
                    && proxyMethod.getReturnType().equals(realMethod.getReturnType())
                    && equalParamTypes(proxyMethod.getParameterTypes(), realMethod.getParameterTypes())) {
                return proxyMethod;
            }
        }
        return realMethod;
    }

    private boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) {
        /* Avoid unnecessary cloning */
        if (params1.length == params2.length) {
            for (int i = 0; i < params1.length; i++) {
                if (params1[i] != params2[i])
                    return false;
            }
            return true;
        }
        return false;
    }

    /**
     * 获得注解ReflectiveService所有的接口
     *
     * @param object 实例
     * @return 包含注解的接口
     */
    private List<Class<?>> getReflectiveInterfaces(Object object) {
        List<Class<?>> interfaces = new ArrayList<Class<?>>();
        Class<?>[] clazzs = ClassUtils.getAllInterfaces(object);
        for (Class<?> clazz : clazzs) {
            ReflectiveService reflectiveService = AnnotationUtils.findAnnotation(clazz, ReflectiveService.class);
            if (reflectiveService != null) {
                interfaces.add(clazz);
            }
        }
        return interfaces;
    }

    /**
     * 获取代理对象的目标对象
     *
     * @param proxy 代理对象
     * @return 返回目标对象
     */
    public static Object getTargetFromProxy(Object proxy) {
        if (!AopUtils.isAopProxy(proxy)) {
            return proxy;//不是代理对象
        }
        try {
            if (AopUtils.isJdkDynamicProxy(proxy)) {
                // javaDynamicProxy
                Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
                h.setAccessible(true);
                AopProxy aopProxy = (AopProxy) h.get(proxy);
                Field advised = aopProxy.getClass().getDeclaredField("advised");
                advised.setAccessible(true);
                return ((AdvisedSupport) advised.get(aopProxy)).getTargetSource().getTarget();
            } else {
                // cglib
                Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
                h.setAccessible(true);
                Object dynamicAdvisedInterceptor = h.get(proxy);
                Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
                advised.setAccessible(true);
                return ((AdvisedSupport) advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
            }
        } catch (Exception e) {
            return null;
        }
    }

    public ICache getCache() {
        return cache;
    }

    public void setCache(ICache cache) {
        this.cache = cache;
    }

    /**
     * service信息
     */
    private static class ServiceInfo {
        Object service;
        ReflectiveService reflectiveAnnotation;
        ReflectiveCache cacheAnnotation;
        Restful restful;

        Map<String, MethodInfo> methods;

        public ServiceInfo(Object service, ReflectiveService reflectiveAnnotation,
                           ReflectiveCache cacheAnnotation, Restful restful) {
            this.service = service;
            this.reflectiveAnnotation = reflectiveAnnotation;
            this.cacheAnnotation = cacheAnnotation;
            this.restful = restful;
            methods = new HashMap<>();
        }
    }

    /**
     * method信息
     */
    private static class MethodInfo {
        Method method;
        ReflectiveMethod reflectiveAnnotation;
        ReflectiveCache cacheAnnotation;

        public MethodInfo(Method method, ReflectiveMethod reflectiveAnnotation, ReflectiveCache cacheAnnotation) {
            this.method = method;
            this.reflectiveAnnotation = reflectiveAnnotation;
            this.cacheAnnotation = cacheAnnotation;
        }
    }

}
